home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 85 / CD Temático 40 Febrero 2004.iso / DOS / testdisk / src / readpart.c < prev    next >
Encoding:
C/C++ Source or Header  |  2004-01-09  |  9.7 KB  |  346 lines

  1. /*
  2.  
  3.     File: readpart.c
  4.  
  5.     Copyright (C) 1998-2004 Christophe GRENIER <grenier@cgsecurity.org>
  6.   
  7.     This software is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU General Public License as published by
  9.     the Free Software Foundation; either version 2 of the License, or
  10.     (at your option) any later version.
  11.   
  12.     This program is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.   
  17.     You should have received a copy of the GNU General Public License
  18.     along with this program; if not, write to the Free Software
  19.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  
  21.  */
  22.  
  23.  
  24. #include <stdio.h>
  25. #include <stdlib.h>     /* qsort */
  26. #include <ctype.h>      /* toupper, tolower */
  27. #include "types.h"
  28. #include "common.h"
  29. #include "readpart.h"
  30. #include "testdisk.h"
  31. #include "fnctdsk.h"
  32. #include "analyse.h"
  33. #include "lang.h"
  34. #include "intrface.h"
  35.  
  36. static t_list_part *get_ext_data(t_param_disk *disk_car, t_list_part *list_part, const int debug);
  37. static void test_MBR_data(t_list_part *list_part);
  38. static int test_MBR_over(t_param_disk *disk_car,t_list_part *list_part);
  39.  
  40. int get_geometry_from_mbr(const unsigned char *buffer, const int debug, t_CHS *geometry)
  41. {
  42.   unsigned int i;
  43.   geometry->cylinder=0;
  44.   geometry->head=0;
  45.   geometry->sector=0;
  46.   if((buffer[0x1FE]!=(unsigned char)0x55)||(buffer[0x1FF]!=(unsigned char)0xAA))
  47.   {
  48.     return 1;
  49.   }
  50.   for(i=0;i<4;i++)
  51.   {
  52.     const struct partition_dos *p=pt_offset_const(buffer,i);
  53.     if(p->sys_ind!=0)
  54.     {
  55.       if(geometry->cylinder<e_cyl(p))
  56.     geometry->cylinder=e_cyl(p);
  57.       if(geometry->head<e_head(p))
  58.     geometry->head=e_head(p);
  59.       if(geometry->sector<e_sect(p))
  60.     geometry->sector=e_sect(p);
  61.     }
  62.   }
  63.   if(geometry->sector>0)
  64.   {
  65.     ecrit_rapport("Geometry from MBR: head=%u sector=%u\n",geometry->head+1,geometry->sector);
  66.   }
  67.   return 0;
  68. }
  69.  
  70. t_list_part *read_part(t_param_disk *disk_car, const int debug)
  71. {
  72.   unsigned char buffer[SECTOR_SIZE];
  73.   t_list_part *new_list_part=NULL;
  74.   unsigned int i;
  75.   int res=0;
  76.   t_CHS geometry;
  77.   aff_buffer(BUFFER_RESET,"Q");
  78.   if(read_MBR(disk_car,&buffer)!=0)
  79.     return NULL;
  80.   if(get_geometry_from_mbr(buffer,debug,&geometry)!=0)
  81.   {
  82.     aff_buffer(BUFFER_ADD,msg_TBL_NMARK);
  83.     return NULL;
  84.   }
  85.   for(i=0;i<4;i++)
  86.   {
  87.     const struct partition_dos *p=pt_offset(buffer,i);
  88.     status_type_t status=STATUS_PRIM;
  89.     switch(p->sys_ind)
  90.     {
  91.       case P_NO_OS:
  92.     break;
  93.       case P_EXTENDX:
  94.       case P_EXTENDED:
  95.       case P_LINUXEXTENDX:
  96.     status=STATUS_EXT;
  97.     /* don't put a break */
  98.       default:
  99.     {
  100.       t_diskext *new_partition=partition_new();
  101.       entry2partition(disk_car, 0, new_partition, p, status,i+1,debug);
  102.       if(debug>1)
  103.         aff_entry_rapport(p);
  104.       aff_part_buffer(AFF_PART_ORDER,disk_car,new_partition);
  105.       if(new_partition->errcode!=BAD_NOERR)
  106.       {
  107.         aff_buffer(BUFFER_ADD,"%s\n",errmsg_entry2partition(new_partition->errcode));
  108.         res|=1;
  109.         FREE(new_partition);
  110.       }
  111.       else
  112.       {
  113.         new_list_part=insert_new_partition(new_list_part,new_partition);
  114.       }
  115.     }
  116.     break;
  117.     }
  118.   }
  119.   if(res==0)
  120.   {
  121.     test_MBR_data(new_list_part);
  122.     if(test_MBR_over(disk_car,new_list_part)==0)
  123.       new_list_part=get_ext_data(disk_car,new_list_part,debug);
  124.   }
  125.   return new_list_part;
  126. }
  127.  
  128. static void test_MBR_data(t_list_part *list_part)
  129. {
  130.   t_list_part *element;
  131.   unsigned int nb_dos=0, nb_hidden=0, nb_mb=0, nb_ext=0, nb_boot=0;
  132.   wdoprintf(stdscr,msg_PART_HEADER);
  133.   for(element=list_part;element!=NULL;element=element->next)
  134.   {
  135.     const t_diskext *partition=element->part;
  136.     switch(partition->status)
  137.     {
  138.       case STATUS_PRIM_BOOT:
  139.     nb_boot++;
  140.       case STATUS_PRIM:
  141.     switch(partition->part_type)
  142.     {
  143.       case P_12FAT:
  144.       case P_16FAT:
  145.       case P_16FATBD:
  146.         nb_dos++;
  147.         break;
  148.       case P_16FATBDH:
  149.       case P_16FATH:
  150.       case P_NTFSH:
  151.         nb_hidden++;
  152.         break;
  153.       case P_OS2MB:
  154.         nb_mb++;
  155.         break;
  156.     }
  157.     break;
  158.       case STATUS_EXT:
  159.     nb_ext++;
  160.     break;
  161.       default:
  162.     ecrit_rapport("test_MBR_data: severe error\n");
  163.     break;
  164.     }
  165.   }
  166.   if(nb_dos>1)
  167.     aff_buffer(BUFFER_ADD,msg_ONLY_ONE_DOS);
  168.   if(nb_ext>1)
  169.     aff_buffer(BUFFER_ADD,msg_ONLY_ONE_EXT);
  170.   /* S'il y a des partitions caches, il faut un MB */
  171.   /* Obsolete
  172.   if(nb_hidden>0 && nb_mb==0)
  173.     aff_buffer(BUFFER_ADD,msg_NO_OS2MB);
  174.     */
  175.   /* Nombre de partition bootable */
  176.   if(nb_boot==0)
  177.     aff_buffer(BUFFER_ADD,msg_NO_BOOTABLE);
  178.   else
  179.     if(nb_boot>1)
  180.       aff_buffer(BUFFER_ADD,msg_ONLY1MUSTBOOT);
  181. }
  182.  
  183. static t_list_part *get_ext_data(t_param_disk *disk_car, t_list_part *list_part, const int debug)
  184. {
  185.   t_list_part *element;
  186.   int res=0;
  187.   t_diskext *partition_main_ext=NULL;
  188.   for(element=list_part;element!=NULL;element=element->next)
  189.   {
  190.     if(element->part->status==STATUS_EXT)
  191.       partition_main_ext=element->part;
  192.   }
  193.   if(partition_main_ext!=NULL)
  194.   {
  195.     t_diskext *partition_ext=partition_main_ext;
  196.     t_diskext *partition_next_ext=NULL;
  197.     unsigned int i;
  198.     unsigned int order=5;
  199.     do
  200.     {
  201.       unsigned char buffer[SECTOR_SIZE];
  202.       int nb_hidden=0, nb_mb=0, nb_part=0, nb_ext=0, nb_boot=0;
  203.       if(disk_car->read(disk_car,1, &buffer, partition_ext->lba)!=0)
  204.     return list_part;
  205.       if((buffer[0x1FE]!=(unsigned char)0x55)||(buffer[0x1FF]!=(unsigned char)0xAA))
  206.       {
  207.     aff_buffer(BUFFER_ADD,"\ntest_logical: " msg_TBL2_NMARK);
  208.     return list_part;
  209.       }
  210.       for(i=0;i<4;i++)
  211.       {
  212.     const struct partition_dos *p=pt_offset(buffer,i);
  213.     if(p->boot_ind==(unsigned char)0x80)
  214.       nb_boot++;
  215.     switch(p->sys_ind)
  216.     {
  217.       case P_16FATBDH:
  218.       case P_16FATH:
  219.       case P_NTFSH:
  220.         nb_hidden++;
  221.         break;
  222.       case P_OS2MB:
  223.         nb_mb++;
  224.         break;
  225.       case P_EXTENDX:
  226.       case P_EXTENDED:
  227.       case P_LINUXEXTENDX:
  228.         nb_ext++;
  229.         break;
  230.       case P_NO_OS:
  231.         break;
  232.       default:
  233.         nb_part++;
  234.     }
  235.       }
  236.       if(nb_hidden>0)
  237.     aff_buffer(BUFFER_ADD,"Partition musn't be hidden\n");
  238.       if(nb_mb>0)
  239.     aff_buffer(BUFFER_ADD,"Multiboot must be a primary partition, not a logical\n");
  240.       if(nb_ext>1)
  241.     aff_buffer(BUFFER_ADD,"A logical partition musn't have more than one link to another logical partition\n");
  242.       if(nb_part>1)
  243.     aff_buffer(BUFFER_ADD,"A logical partition must contain only one partition\n");
  244.       if(nb_boot>0)
  245.     aff_buffer(BUFFER_ADD,"Logical partition musn't be bootable\n");
  246.       partition_next_ext=NULL;
  247.       for(i=0;i<4;i++)
  248.       {
  249.     const struct partition_dos *p=pt_offset(buffer,i);
  250.     if(p->sys_ind!=0)
  251.     {
  252.       t_diskext *new_partition=partition_new();
  253.       new_partition->order=order;
  254.       if(debug>1)
  255.         aff_entry_rapport(p);
  256.       if(is_extended(p->sys_ind))
  257.       {
  258.         partition_next_ext=new_partition;
  259.         entry2partition(disk_car, partition_main_ext->lba, new_partition, p, STATUS_EXT_IN_EXT,order,debug);
  260.         aff_part_buffer(AFF_PART_ORDER,disk_car,new_partition);
  261.         if(new_partition->errcode!=BAD_NOERR)
  262.         {
  263.           aff_buffer(BUFFER_ADD,"(p): %s\n",errmsg_entry2partition(new_partition->errcode));
  264.           res=1;
  265.         }
  266.         else
  267.         {
  268.           if((new_partition->lba<=partition_main_ext->lba) ||
  269.           (new_partition->lba+new_partition->part_size-1 > partition_main_ext->lba+partition_main_ext->part_size-1))
  270.           {    /* Must be IN partition_main_ext */
  271.         res=1;
  272.         aff_buffer(BUFFER_ADD,"Must be in extended partition\n");
  273.         aff_part_buffer(AFF_PART_ORDER,disk_car,partition_main_ext);
  274.         aff_part_buffer(AFF_PART_ORDER,disk_car,new_partition);
  275.           }
  276.           else
  277.           {
  278.         for(element=list_part;element!=NULL;element=element->next)
  279.         {
  280.           t_diskext *partition=element->part;
  281.           if(partition->status==STATUS_EXT_IN_EXT)
  282.           {
  283.             if(((partition->lba>=new_partition->lba) && (partition->lba<=new_partition->lba+new_partition->part_size-1)) ||
  284.             ((partition->lba+partition->part_size-1>=new_partition->lba) && (partition->lba+partition->part_size-1<=new_partition->lba+partition->part_size-1)))
  285.             { /* New Partition start or end musn't been in partition */
  286.               res=1;
  287.               aff_buffer(BUFFER_ADD, "Logical partition must be in its own extended partition\n");
  288.               aff_part_buffer(AFF_PART_ORDER,disk_car,partition);
  289.               aff_part_buffer(AFF_PART_ORDER,disk_car,new_partition);
  290.             }
  291.           }
  292.         }
  293.           }
  294.         }
  295.       }
  296.       else
  297.       {
  298.         entry2partition(disk_car,partition_ext->lba, new_partition, p, STATUS_LOG,order,debug);
  299.         order++;
  300.         if(debug>1)
  301.           aff_entry_rapport(p);
  302.         aff_part_buffer(AFF_PART_ORDER,disk_car,new_partition);
  303.         if(new_partition->errcode!=BAD_NOERR)
  304.         {
  305.           aff_buffer(BUFFER_ADD,"%s\n",errmsg_entry2partition(new_partition->errcode));
  306.           res=1;
  307.         }
  308.         else
  309.         {
  310.           if((new_partition->lba<=partition_main_ext->lba) ||
  311.           (new_partition->lba+new_partition->part_size-1 > partition_main_ext->lba+partition_main_ext->part_size-1))
  312.           {    /* Must be IN partition_main_ext */
  313.         res=1;
  314.         aff_buffer(BUFFER_ADD, msg_SAME_SPACE);
  315.         aff_part_buffer(AFF_PART_ORDER,disk_car,partition_main_ext);
  316.         aff_part_buffer(AFF_PART_ORDER,disk_car,new_partition);
  317.           }
  318.         }
  319.       }
  320.       if(res!=0)
  321.         FREE(new_partition);
  322.       else
  323.         list_part=insert_new_partition(list_part,new_partition);
  324.     }
  325.       }
  326.       partition_ext=partition_next_ext;
  327.     } while ((res==0) && (partition_ext!=NULL) && (order<30));
  328.   }
  329.   return list_part;
  330. }
  331.  
  332. static int test_MBR_over(t_param_disk *disk_car,t_list_part *list_part)
  333. {/* Tester le chevauchement des partitions */
  334.   int res=0;
  335.   t_list_part *element;
  336.   for(element=list_part;element!=NULL;element=element->next)
  337.     if((element->next!=NULL) && (element->part->lba + element->part->part_size - 1 >= element->next->part->lba))
  338.     {
  339.       res=1;
  340.       aff_buffer(BUFFER_ADD, msg_SAME_SPACE);
  341.       aff_part_buffer(AFF_PART_ORDER,disk_car,element->part);
  342.       aff_part_buffer(AFF_PART_ORDER,disk_car,element->next->part);
  343.     }
  344.   return res;
  345. }
  346.